package com.easybuilder.core.authorization.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.interfaces.Claim;
import com.easybuilder.common.utils.DES;
import com.easybuilder.common.utils.JwtUtil;
import com.easybuilder.common.utils.RedisUtil;
import com.easybuilder.common.utils.ServletUtil;
import com.easybuilder.core.authorization.entity.SysGiteeUser;
import com.easybuilder.core.authorization.service.LoginService;
import com.easybuilder.core.rbac.entity.SysUser;
import com.easybuilder.core.rbac.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    /** 注册锁 */
    private static final Object REGIST_LOCK = new Object();

    private static final String KEY = "TOPZXS";

    @Resource
    private SysUserService sysUserService;

    @Override
    public SysUser login(String username, String password) {
        UserDetails userDetails = sysUserService.loadUserByUsername(username);
        if (userDetails != null) {
            SysUser user = (SysUser) userDetails;
            String pwd = user.getPassword();
            if (new DES(KEY).encrypt(password).equals(pwd)) {
                String token = JwtUtil.buildToken(username, password, "SYS");
                // 设置认证信息到响应头中
                ServletUtil.setToken(token);
                // 保存用户信息到redis（redis保存用户信息3小时，token设置有效时间2小时，如果失效时间 < 1小时，达到自动续命的效果）
                RedisUtil.setValue("USER_SYS_"+username, user, 3L, TimeUnit.HOURS);
                SysUser value = RedisUtil.getValue("USER_SYS_" + username, SysUser.class);
                log.info("redis获取用户信息：" + JSONObject.toJSONString(value));
                return user;
            }
        }
        return null;
    }

    /****
     * @description: 退出登录
     * @param:
     * @param token
     * @return:
     * @author ZXS
     * @date: 2022-1-29 21:14
     */
    @Override
    public boolean logout(String token) {
        // 解析token
        Map<String, Claim> calims = JwtUtil.resolveToken(token);
        // 获取用户名
        String username = calims.get("username").asString();
        // 清除redis存储的用户信息
        RedisUtil.setValue("USERNAME_"+username, null);
        // 清除User上下文中的信息
        return true;
    }


    /** 检查登陆状态 */
    @Override
    public boolean check(String token) {
        // 解析token
        Map<String, Claim> calims = JwtUtil.resolveToken(token);
        // 获取用户名
        String username = calims.get("username").asString();
        String type = calims.get("type").asString();
        // 获取redis存储的用户信息
        Object user = null;
        if ("SYS".equals(type)) {
            user = RedisUtil.getValue("USER_"+type+"_" + username, SysUser.class);
        } else if ("GITEE".equals(type)) {
            user = RedisUtil.getValue("USER_"+type+"_" + username, SysGiteeUser.class);
        }
        // 判断用户是否为空，不为空：登陆状态；为空：未登录状态；
        return user != null;
    }


    /** 注册账号 */
    @Override
    public JSONObject regist(SysUser sysUser) {
        JSONObject result = new JSONObject();
        UserDetails user = sysUserService.loadUserByUsername(sysUser.getUsername());
        if (user != null) {
            result.put("success", false);
            result.put("message", "账号已存在");
            return result;
        } else {
            // 同步 + 双重判断，防止并发注册同一个账号，产生异常数据
            synchronized (REGIST_LOCK) {
                // 密码加密
                sysUser.setPassword(new DES(KEY).encrypt(sysUser.getPassword()));
                // 设置头像
                setImg(sysUser);
                user = sysUserService.loadUserByUsername(sysUser.getUsername());
                if (user != null) {
                    result.put("success", false);
                    result.put("message", "账号已存在");
                    return result;
                } else {
                    int insert = sysUserService.insert(sysUser);
                    String message = insert > 0 ? "注册成功" : "注册失败";
                    result.put("success", insert > 0);
                    result.put("message", message);
                    return result;
                }
            }
        }
    }

    /** 设置头像路径 */
    private void setImg(SysUser sysUser) {
        Random random = new Random();
        int index = Math.abs(random.nextInt(7)) + 1;
        StringBuilder img = new StringBuilder("/file/user/");
        if ("1".equals(sysUser.getGender() + "")) { // 男
            img.append("男").append(index);
        } else { // 女
            img.append("女").append(index);
        }
        img.append(".png");
        sysUser.setImg(img.toString());
    }

}

